package jk.fox.config;

import jk.fox.common.payload.container.DefaultRpcContainer;
import jk.fox.common.payload.container.RpcContainer;
import jk.fox.common.payload.message.MessageDispatcher;
import jk.fox.config.exchange.ExchangeConfiguration;
import jk.fox.config.exchange.ExchangeConfigurationBuilder;
import jk.fox.config.exchange.standard.DefaultExchangeConfigurationBuilder;
import jk.fox.config.registry.RegistryConfiguration;
import jk.fox.config.registry.RegistryConfigurationBuilder;
import jk.fox.config.registry.zookeeper.ZookeeperConfigurationBuilder;
import jk.fox.config.transport.TransportConfiguration;
import jk.fox.config.transport.TransportConfigurationBuilder;
import jk.fox.config.transport.netty.NettyConfigurationBuilder;
import jk.fox.node.StandardMessageDispatcher;
import jk.fox.node.rule.RoundRobinRuleFactory;
import jk.fox.node.rule.RuleFactory;
import lombok.Getter;
import lombok.Setter;

/**
 * rpc框架统一配置类
 * @author cuichao
 * @Description: RpcConfig
 * @Date: create in 2020/5/14 15:24
 */
@Getter
@Setter
public class RpcConfiguration {
    /**
     * 服务暴露的接口
     */
    private int expose;
    /**
     * 是否允许同源调用
     */
    private boolean enableSameSource = true;
    /**
     * 请求超时时间
     */
    private long requestTimeOutMs = 3000;
    /**
     * 是否允许request超时重试
     */
    private boolean enableRequestRetry = false;
    /**
     * 请求最大重试次数
     */
    private int requestMaxRetires = 3;



    private RpcContainer container;
    private RuleFactory ruleFactory;
    private MessageDispatcher messageDispatcher;
    private RegistryConfiguration  registryConfig;
    private TransportConfiguration transportConfig;
    private ExchangeConfiguration  exchangeConfig;

    public static RpcConfigBuilder builder(){
        return new RpcConfigBuilder();
    }


    public static class RpcConfigBuilder {

        private RpcConfiguration rpcConfig;
        private RpcContainer container;
        private RuleFactory ruleFactory;
        private MessageDispatcher messageDispatcher;
        private RegistryConfigurationBuilder  registryConfigurationBuilder;
        private TransportConfigurationBuilder transportConfigurationBuilder;
        private ExchangeConfigurationBuilder  exchangeConfigurationBuilder;



        public RpcConfigBuilder(){
            rpcConfig = new RpcConfiguration();
        }



        public RpcConfiguration build(){
            if(container == null ){
                container = new DefaultRpcContainer();
            }
            if(messageDispatcher == null ){
                messageDispatcher = new StandardMessageDispatcher();
            }
            if(ruleFactory == null){
                ruleFactory = new RoundRobinRuleFactory();
            }
            if(transportConfigurationBuilder == null){
                transportConfigurationBuilder = new NettyConfigurationBuilder(this);
            }
            if(registryConfigurationBuilder == null ){
                registryConfigurationBuilder = new ZookeeperConfigurationBuilder(this);
            }
            if(exchangeConfigurationBuilder == null){
                exchangeConfigurationBuilder = new DefaultExchangeConfigurationBuilder(this);
            }
            /*container*/
            rpcConfig.setContainer(container);
            /*dispatcher*/
            rpcConfig.setMessageDispatcher(messageDispatcher);
            /*rule*/
            rpcConfig.setRuleFactory(ruleFactory);
            /*registry*/
            RegistryConfiguration registryConfig = registryConfigurationBuilder.build();
            rpcConfig.setRegistryConfig(registryConfig);
            /*transporter*/
            TransportConfiguration transportConfig = transportConfigurationBuilder.build();
            transportConfig.setServerPort(rpcConfig.expose);
            rpcConfig.setTransportConfig(transportConfig);
            /*exchange*/
            ExchangeConfiguration exchangeConfiguration = exchangeConfigurationBuilder.build();
            rpcConfig.setExchangeConfig(exchangeConfiguration);
            return rpcConfig;
        }

        public RpcConfigBuilder expose(int port){
            rpcConfig.setExpose(port);
            return this;
        }

        public RpcConfigBuilder enableSameSource(boolean enable){
            rpcConfig.setEnableSameSource(enable);
            return this;
        }

        public RpcConfigBuilder requestTimeOutMs(long timeout){
            if(timeout > 0){
                rpcConfig.setRequestTimeOutMs(timeout);
            }
            return this;
        }

        public RpcConfigBuilder enableRequestRetry(boolean enable){
            rpcConfig.enableRequestRetry = enable;
            return this;
        }

        public RpcConfigBuilder requestMaxRetires(int retires){
            if(retires > 0){
                rpcConfig.requestMaxRetires = retires;
            }
            return this;
        }



        public RpcConfigBuilder ruleFactory(RuleFactory ruleFactory){
            this.ruleFactory = ruleFactory;
            return this;
        }

        public RpcConfigBuilder dispatcher(MessageDispatcher dispatcher){
            this.messageDispatcher = dispatcher;
            return this;
        }

        /************************************************transport-start**************************************************************/
        public NettyConfigurationBuilder netty(){
            NettyConfigurationBuilder nettyBuilder = new NettyConfigurationBuilder(this);
            this.transportConfigurationBuilder = new NettyConfigurationBuilder(this);
            return nettyBuilder;
        }
        /************************************************serverExchange-start**************************************************************/
        public DefaultExchangeConfigurationBuilder exchange(){
            DefaultExchangeConfigurationBuilder exchangeConfigurationBuilder = new DefaultExchangeConfigurationBuilder(this);
            this.exchangeConfigurationBuilder = exchangeConfigurationBuilder;
            return exchangeConfigurationBuilder;
        }

        /************************************************registry-start**************************************************************/
        public ZookeeperConfigurationBuilder zookeeper(){
            ZookeeperConfigurationBuilder zookeeperBuilder = new ZookeeperConfigurationBuilder(this);
            this.registryConfigurationBuilder = zookeeperBuilder;
            return zookeeperBuilder;
        }



    }







}
